package com.cloud.logger.zchain.zchainserver.config;

import com.cloud.logger.zchain.core.common.properties.ServerInfo;
import com.cloud.logger.zchain.core.constants.Constants;
import com.cloud.logger.zchain.core.zookeeper.DefaultConnectionStateListener;
import com.cloud.logger.zchain.core.zookeeper.LeaderElection;
import com.cloud.logger.zchain.core.zookeeper.ZookeeperFactory;
import com.cloud.logger.zchain.support.ScheduleAnnotaion;
import com.cloud.logger.zchain.zchainserver.entity.AngelaLoggerProjectNode;
import com.cloud.logger.zchain.zchainserver.entity.propertyenum.SwitchEnum;
import com.cloud.logger.zchain.zchainserver.mongo.AngelaProjectNodeRepository;
import com.cloud.logger.zchain.zchainserver.service.AngelaLoggerProjectService;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.zookeeper.data.Stat;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.List;

@Configuration
public class SchedulingConfig {

    @Resource
    AngelaLoggerProjectService angelaLoggerProjectService;

    @Resource
    private AngelaProjectNodeRepository nodeRepository;

    @Bean
    public ZookeeperFactory zookeeperFactory(){

        try {
            ZookeeperFactory zookeeperFactory = ZookeeperFactory.getInstance();
            zookeeperFactory.init("115.159.160.97:2181","zchain-server",5000);


            PathChildrenCache cache = new PathChildrenCache(zookeeperFactory.getZkTools(), Constants.ZK_PROJECT_PATH, true);
            cache.start();

            PathChildrenCacheListener cacheListener = (zkTools, event) -> {
                String leader = LeaderElection.getLeader();
                if(leader!=null && leader.equals(ServerInfo.scheduleNode)){
                    switch (event.getType()) {
                        case CHILD_ADDED: {
                            byte[] data = event.getData().getData();
                            String dataStr = new String(data);
                            try {
                                System.out.println(dataStr+"启动");
                                angelaLoggerProjectService.startProject(dataStr);
                            }catch (Exception ex){
                                System.out.println("项目启动失败"+dataStr);
                            }
                            break;
                        }
                        case CHILD_REMOVED: {
                            byte[] data = event.getData().getData();
                            String dataStr = new String(data);
                            try {
                                angelaLoggerProjectService.shutDownProject(dataStr);
                            }catch (Exception ex){
                                System.out.println("项目关闭失败"+dataStr);
                            }
                            break;
                        }
                    }
                }
            };
            cache.getListenable().addListener(cacheListener);
            updateServerList(zookeeperFactory.getZkTools());

            return zookeeperFactory;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private void updateServerList(CuratorFramework client) throws Exception {
        Gson gson = new GsonBuilder().create();

        List<AngelaLoggerProjectNode> nodes = nodeRepository.findAll();

        for(AngelaLoggerProjectNode node : nodes){
            String path =Constants.ZK_PROJECT_PATH
                    +Constants.SEPARATOR
                    +node.getCode()
                    +Constants.RAIL
                    +node.getIp()
                    +Constants.RAIL
                    +node.getPort();
            Stat stat = client.checkExists().forPath(path);
            try {
                if(stat==null && node.getStatus().equals(SwitchEnum.on))
                    angelaLoggerProjectService.shutDownProject(gson.toJson(node));
                else if(stat!=null)
                    angelaLoggerProjectService.startProject(gson.toJson(node));
            }catch (Exception ex){
                client.delete().forPath(path);
            }

        }
        System.out.println("初始化服务状态开启成功");
    }

    @Bean
    public DefaultConnectionStateListener defaultConnectionStateListener(){
       return new DefaultConnectionStateListener();
    }

    @Bean
    public ScheduleAnnotaion scheduleAnnotaion(){
        return new ScheduleAnnotaion();
    }
}